package de.stefanocke.roo.kontaktliste.infrastructure;

import java.util.Locale;

import javax.validation.MessageInterpolator;

import org.hibernate.validator.messageinterpolation.ResourceBundleMessageInterpolator;
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.ParserContext;
import org.springframework.expression.common.TemplateParserContext;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;

/**
 * A MessageInterpolator that allows the message template to contain SpEL expressions.
 * It uses the object to be validated as root object. So it can be used in the template as #{#root}.
 * Moreover, the locale is provided as evaluation context variable named "locale".  
 * @author stoc
 *
 */
public class SpelMessageInterpolator implements MessageInterpolator {
	
	private MessageInterpolator delegate = new ResourceBundleMessageInterpolator();
	
	private ExpressionParser parser = new SpelExpressionParser();
	
	private ParserContext templateContext = new TemplateParserContext();

	
	@Override
	public String interpolate(String messageTemplate, Context context) {
		String msg = replaceVariables(messageTemplate, context.getValidatedValue(), null);
		return delegate.interpolate(msg, context);
	}

	@Override
	public String interpolate(String messageTemplate, Context context, Locale locale) {
		String msg = replaceVariables(messageTemplate, context.getValidatedValue(), locale);
		return delegate.interpolate(msg, context, locale);
	}

	/**Variablen mittels SpEL ersetzen*/
	private String replaceVariables(String message, Object validatedValue, Locale locale) {
		
		Expression exp = parser.parseExpression(message, templateContext);
		StandardEvaluationContext context = new StandardEvaluationContext(validatedValue);
		context.setVariable("locale", locale);
		return (String) exp.getValue(context);
	}


	
	
}
